#pragma once
#include <iostream>
#include <unistd.h>
#include <string>
#include <vector>
#include <stdio.h>
#include <sys/time.h>
#include <stdarg.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <sys/wait.h>
#include <pthread.h>
#include <functional>
#include <jsoncpp/json/json.h>

using namespace std;

enum log_type
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};

enum
{
    SOCKET_ERROR = 1,
    BIND_ERROR,
    LISTEN_ERROR,
    ACCEPT_ERROR,
    INPUT_ERROR,
    CONNECT_ERROR
};

string get_time()
{
    // 获取时间
    struct tm *tmp;
    time_t cur_time = time(nullptr); // time_t == long int
    //struct tm {
    //            int tm_sec;    /* Seconds (0-60) */
    //            int tm_min;    /* Minutes (0-59) */
    //            int tm_hour;   /* Hours (0-23) */
    //            int tm_mday;   /* Day of the month (1-31) */
    //            int tm_mon;    /* Month (0-11) */
    //            int tm_year;   /* Year - 1900 */
    //            int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
    //            int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
    //            int tm_isdst;  /* Daylight saving time */
    //        };

    tmp = localtime(&cur_time);

    char arr[1024];
    snprintf(arr, sizeof(arr), "%d_%d_%d %d:%d:%d",
             tmp->tm_year + 1900,
             tmp->tm_mon + 1,
             tmp->tm_mday,
             tmp->tm_hour,
             tmp->tm_min,
             tmp->tm_sec);
    return arr;
}

string level_to_str(int level)
{
    switch (level)
    {
    case DEBUG:
        return "DEBUG";
    case INFO:
        return "INFO";
    case WARNING:
        return "WARNING";
    case ERROR:
        return "ERROR";
    case FATAL:
        return "FATAL";
    default:
        return "none lever";
    }
}

// 日志等级 时间 代码所在的文件名/行数 日志的内容
void log_function(string filename, int line, int level, const char *format, ...)
{
    string level_name = level_to_str(level);
    string cur_time = get_time();

    char arr[1024];
    va_list arg;
    va_start(arg, format);

    vsnprintf(arr, sizeof(arr), format, arg);

    va_end(arg);
    cout << "[" << cur_time << "]"
         << "[" << level_name << "]"
         << "[" << filename << "]"
         << "[" << line << "]"
         << "[" << arr << "]" << endl;
}

#define log(level, format, ...) log_function(__FILE__, __LINE__, level, format, ##__VA_ARGS__)